; 简单的ZENrs引导加载程序示例
; 这是一个基本的BIOS引导扇区示例，展示了如何实现简单的引导功能
; 注意：这只是一个示例，实际的引导加载程序会更复杂

[BITS 16]           ; 16位模式
[ORG 0x7C00]        ; 引导扇区加载地址

; 主引导程序入口
start:
    ; 初始化段寄存器
    mov ax, 0x0000  ; 段地址为0
    mov ds, ax      ; 数据段
    mov es, ax      ; 附加段
    mov ss, ax      ; 栈段
    mov sp, 0x7C00  ; 栈指针指向引导扇区上方
    
    ; 清除屏幕
    call clear_screen
    
    ; 显示欢迎信息
    mov si, welcome_msg
    call print_string
    
    ; 检测内存（简化版）
    call detect_memory
    
    ; 加载内核（简化版）
    call load_kernel
    
    ; 跳转到保护模式
    call enter_protected_mode
    
    ; 无限循环（防止执行到后面的垃圾代码）
    jmp $

; 清除屏幕函数
clear_screen:
    mov ah, 0x06    ; 功能号：向上滚动窗口
    mov al, 0x00    ; 清除整个屏幕
    mov bh, 0x07    ; 背景色：黑色，前景色：白色
    mov cx, 0x0000  ; 左上角：行0，列0
    mov dx, 0x184F  ; 右下角：行24，列79
    int 0x10        ; 调用BIOS中断
    ret

; 打印字符串函数
print_string:
    mov ah, 0x0E    ; 功能号：在Teletype模式下显示字符
    mov bh, 0x00    ; 页码
    mov bl, 0x07    ; 属性：白色
.print_char:
    lodsb           ; 加载DS:SI指向的字节到AL
    cmp al, 0       ; 检查是否为字符串结束符
    je .print_done  ; 如果是，结束打印
    int 0x10        ; 调用BIOS中断显示字符
    jmp .print_char ; 继续打印下一个字符
.print_done:
    ret

; 检测内存函数（简化版）
detect_memory:
    mov si, memory_detect_msg
    call print_string
    
    ; 这里应该有更复杂的内存检测代码
    ; 简化版本只是显示一条消息
    
    ret

; 加载内核函数（简化版）
load_kernel:
    mov si, load_kernel_msg
    call print_string
    
    ; 设置磁盘读取参数
    mov ah, 0x02    ; 功能号：读扇区
    mov al, 0x08    ; 要读取的扇区数
    mov ch, 0x00    ; 柱面号
    mov cl, 0x02    ; 扇区号
    mov dh, 0x00    ; 磁头号
    mov dl, 0x80    ; 驱动器号（0x80表示第一个硬盘）
    mov bx, 0x1000  ; 目标地址：ES:BX = 0x0000:0x1000
    int 0x13        ; 调用BIOS磁盘中断
    
    ; 检查读取是否成功
    jc .load_error  ; 如果进位标志为1，表示出错
    
    mov si, load_success_msg
    call print_string
    jmp .load_done
    
.load_error:
    mov si, load_error_msg
    call print_string
    
.load_done:
    ret

; 进入保护模式函数
enter_protected_mode:
    mov si, enter_pm_msg
    call print_string
    
    ; 禁用中断
    cli
    
    ; 加载全局描述符表
    lgdt [gdt_descriptor]
    
    ; 设置CR0寄存器的PE位（保护模式启用位）
    mov eax, cr0
    or eax, 0x00000001
    mov cr0, eax
    
    ; 远跳转，刷新CS寄存器
    jmp CODE_SEG:init_protected_mode

; 全局描述符表
[GLOBAL gdt_start]
[GLOBAL gdt_end]

gdt_start:
    ; 空描述符
    dd 0x0
    dd 0x0
    
    ; 代码段描述符
    dw 0xFFFF       ; 段界限低16位
    dw 0x0000       ; 段基址低16位
    db 0x00         ; 段基址中8位
    db 0x9A         ; 访问权限字节：代码段，可读可执行
    db 0xCF         ; 段界限高4位和标志位
    db 0x00         ; 段基址高8位
    
    ; 数据段描述符
    dw 0xFFFF       ; 段界限低16位
    dw 0x0000       ; 段基址低16位
    db 0x00         ; 段基址中8位
    db 0x92         ; 访问权限字节：数据段，可读写
    db 0xCF         ; 段界限高4位和标志位
    db 0x00         ; 段基址高8位

gdt_end:
    
    ; GDT描述符
    gdt_descriptor:
        dw gdt_end - gdt_start - 1  ; 界限
        dd gdt_start                ; 基址

; 保护模式初始化
[BITS 32]
init_protected_mode:
    ; 初始化数据段寄存器
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    
    ; 设置栈指针
    mov ebp, 0x90000
    mov esp, ebp
    
    ; 跳转到内核加载地址
    jmp 0x1000
    
    ; 保护模式下的无限循环
    jmp $

; 定义常量
CODE_SEG equ gdt_start + 0x08
DATA_SEG equ gdt_start + 0x10

; 定义字符串
welcome_msg db 'ZENrs Bootloader v0.1', 0x0D, 0x0A, 'Loading ZENrs Operating System...', 0x0D, 0x0A, 0
memory_detect_msg db 'Detecting memory...', 0x0D, 0x0A, 0
load_kernel_msg db 'Loading kernel from disk...', 0x0D, 0x0A, 0
load_success_msg db 'Kernel loaded successfully!', 0x0D, 0x0A, 0
load_error_msg db 'Error loading kernel!', 0x0D, 0x0A, 0
enter_pm_msg db 'Entering protected mode...', 0x0D, 0x0A, 0

; 填充剩余空间并添加引导扇区标记
times 510-($-$$) db 0
dw 0xAA55  ; 引导扇区标记